fix(config): bypass proxy for loopback backend calls - #924
Open
ajdevy wants to merge 1 commit into
Open
Conversation
The config CLI built its HTTP client with reqwest::Client::new(), which honours HTTP_PROXY/HTTPS_PROXY and has no loopback exemption. The AionUi backend listens on loopback, so any proxy exported for unrelated traffic captured these local calls. The failure was misleading: requests never reached the router, so they were absent from aioncore.log while the backend served 200 for the same route, and the CLI reported CONFIG_HTTP_STATUS_ERROR ... status="503": AionUi backend returned an error status. That points at a healthy backend. config capabilities kept working because it answers locally, which made the CLI look partly alive and reinforced the wrong diagnosis. Build the client with no_proxy() when AIONUI_BASE_URL is loopback. A remote base URL keeps the proxy environment, since reaching it may depend on the proxy.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
aioncore configbuilds its HTTP client withreqwest::Client::new(), which honoursHTTP_PROXY/HTTPS_PROXYand has no loopback exemption. The backend listens on loopback, so any proxy exported for unrelated traffic captures these local calls and noconfigsubcommand works.The failure mode actively misleads. The CLI reports:
That accuses the backend, but the backend is healthy — it serves
200for the same route at the same moment, and the failing requests are absent fromaioncore.logentirely, because they never reach the router.config capabilitieskeeps working, since it answers locally without touching the backend, which makes the CLI look partly alive and reinforces the wrong diagnosis.I lost a while to this: I checked backend uptime, the DB lock files and the WAL, and concluded the backend was rejecting my session. The actual cause was one environment variable. Any tool that exports a proxy for its own traffic breaks every subsequent
configcall in that shell — in my caseclaude-vpssetsHTTP_PROXY=http://127.0.0.1:13128for its tunnel.Reported as #4145 on iOfficeAI/AionUi.
Fix
Build the client with
no_proxy()whenAIONUI_BASE_URLpoints at loopback. A remote base URL keeps the proxy environment, since reaching it may legitimately depend on the proxy. An unparseable or absent base URL is handled conservatively.Verification
Same machine, same running backend, proxy exported in both cases:
config skills listCONFIG_HTTP_STATUS_ERROR ... status="503"success: true, 50 skillsGates, all green on
aionui-app:cargo test -p aionui-app --bin aioncore cmd_config::tests— 5 passed, 0 failed (2 new)cargo fmt --all -- --check— cleancargo clippy -p aionui-app --bin aioncore -- -D warnings— cleanThe two added tests cover loopback IPv4 including the wider
127.0.0.0/8,localhostcase-insensitively, the[::1]bracketed IPv6 literal, and the negative cases — a LAN address, a public host,localhost.example.com(a host that merely starts with the loopback label), and an unparseable base URL.Note on a separate issue
While working around this I hit a second problem, not addressed here since it is independent:
config skills importreports per-skill rejections insidedata.failed[]while still settingsuccess: trueon the envelope.{"success": true, "data": {"skill_name": "", "failed": [{"source_name": "kazoo-github-pr", "code": "SKILL_INVALID_FRONTMATTER"}]}}Importing a parent directory made this concrete: 23 of 25 skills imported, two were dropped, and the envelope still said
success: true. A caller that checkssuccess— which the agent-facing contract encourages — cannot distinguish a full import from a partial one. Happy to send a second PR if you want the envelope to reflect partial failure.